package com.wang.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wang.dao.mapper.ArticleBodyMapper;
import com.wang.dao.mapper.ArticleMapper;
import com.wang.dao.mapper.ArticleTagMapper;
import com.wang.pojo.*;
import com.wang.utils.UserThreadLocal;
import com.wang.vo.ArticleBodyVo;
import com.wang.vo.ArticleVo;
import com.wang.vo.Result;
import com.wang.vo.TagVo;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
public class ArticleServiceImpl implements ArticleService{

    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private TagService tagService;
    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private ArticleBodyMapper articleBodyMapper;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private ThreadService threadService;

    @Autowired
    private ArticleTagMapper articleTagMapper;

    @Override
    public Result listArticlePage(int index, int pageSize) {
        //封装请求页
        Page<Article> page = new Page<>(index, pageSize);
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        //排序
        queryWrapper.orderByDesc(Article::getWeight, Article::getCreateDate);

        Page<Article> articlePage = articleMapper.selectPage(page, queryWrapper);
        List<Article> records = articlePage.getRecords();
        long total = articlePage.getTotal();
        //实体类数据映射为vo数据
        List<ArticleVo> articleVoList = copyList(records, true, true);

        return Result.success(articleVoList, total);
    }

    @Override
    public Result listArticleByTagIdPage(List<Long> list, Long tagId, long total) {
        //封装请求页
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Article::getId,list);
        //排序
        queryWrapper.orderByDesc(Article::getWeight, Article::getCreateDate);

        List<Article> articleList = articleMapper.selectList(queryWrapper);
        //实体类数据映射为vo数据
        List<ArticleVo> articleVoList = copyList(articleList, true, true);


        return Result.success(articleVoList, total);
    }

    @Override
    public Result listArticleByCategoryIdPage(Page<Article> articlePage, Long categoryId) {

        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Article::getCategoryId, categoryId);
        queryWrapper.orderByDesc(Article::getWeight, Article::getCreateDate);

        Page<Article> page = articleMapper.selectPage(articlePage, queryWrapper);
        List<Article> records = page.getRecords();
        long total = page.getTotal();
        return Result.success(copyList(records, true, true), total);
    }


    @Override
    public Result hotsArticle(int limit) {
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Article::getCommentCounts);
        queryWrapper.select(Article::getId, Article::getTitle);
        queryWrapper.last("limit " + limit);
        List<Article> articles = articleMapper.selectList(queryWrapper);
        return Result.success(copyList(articles, false, false));
    }

    @Override
    public Result newArticle(int limit) {
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Article::getCreateDate);
        queryWrapper.select(Article::getId, Article::getTitle);
        queryWrapper.last("limit " + limit);
        List<Article> articles = articleMapper.selectList(queryWrapper);
        return Result.success(copyList(articles, false, false));
    }

    @Override
    public Result ListArchives() {
        List<Archives> archivesVos = articleMapper.ListArchives();
        return Result.success(archivesVos);
    }

    @Override
    public Result ListArticleByArchives(ArchivesParams archivesParams) {

        List<Article> articleList = articleMapper.ListArticleByArchives(archivesParams);
        return Result.success(copyList(articleList, true, true));
    }

    @Override
    public Result detail(Long id) {
        Article article = articleMapper.selectById(id);
        threadService.updateArticleViewCount(articleMapper, article);
        return Result.success(copy(article, true, true, true, true));
    }

    @Transactional
    @Override
    public Result addArticle(ArticleParam articleParam) {
        SysUser sysUser = UserThreadLocal.get();

        Article article = new Article();
        article.setCreateDate(System.currentTimeMillis());
        article.setAuthorId(sysUser.getId());
        article.setSummary(articleParam.getSummary());
        article.setTitle(articleParam.getTitle());
        article.setWeight(Article.Article_Common);
        article.setCommentCounts(0);
        article.setCategoryId(articleParam.getCategory().getId());
        article.setViewCounts(0);
        article.setBodyId(-1l);

        articleMapper.insert(article);

        List<TagVo> tags = articleParam.getTags();
        if(tags != null) {
            for (TagVo tag : tags) {
                ArticleTag articleTag = new ArticleTag();
                articleTag.setArticleId(article.getId());
                articleTag.setTagId(tag.getId());
                articleTagMapper.insert(articleTag);
            }
        }

        ArticleBody articleBody = new ArticleBody();
        articleBody.setArticleId(article.getId());
        articleBody.setContent(articleParam.getBody().getContent());
        articleBody.setContentHtml(articleParam.getBody().getContentHtml());
        articleBodyMapper.insert(articleBody);

        article.setBodyId(articleBody.getId());
        int i = articleMapper.updateById(article);
        if(i != 0) {
            return Result.success(true);
        }else {
            return Result.fail(345, "添加失败");
        }
    }

    @Transactional
    @Override
    public void updateById(Article article) {
        articleMapper.updateById(article);
    }

    @Override
    public Article getArticleById(long id) {
        return articleMapper.selectById(id);
    }

    private List<ArticleVo> copyList(List<Article> records, boolean isTag, boolean isAuthor) {
        List<ArticleVo> articleVoList = new ArrayList<>();
        for (Article record : records) {
            articleVoList.add(copy(record, isTag, isAuthor, false, false));
        }
        return articleVoList;
    }

    private List<ArticleVo> copyList(List<Article> records, boolean isTag, boolean isAuthor, boolean isBody, boolean isCategory) {
        List<ArticleVo> articleVoList = new ArrayList<>();
        for (Article record : records) {
            articleVoList.add(copy(record, isTag, isAuthor, isBody, isCategory));
        }
        return articleVoList;
    }

    private ArticleVo copy(Article article, boolean isTag, boolean isAuthor, boolean isBody,boolean isCategory) {
        ArticleVo articleVo = new ArticleVo();
        BeanUtils.copyProperties(article, articleVo);
        articleVo.setCreateDate(new DateTime(article.getCreateDate()).toString("yyyy-MM-dd HH:mm"));
        if(isTag) {
            Long articleId = article.getId();
            articleVo.setTags(tagService.findTagsByArticleId(articleId));
        }
        if (isAuthor) {
            Long authorId = article.getAuthorId();
            articleVo.setAuthor(sysUserService.findUserById(authorId).getNickname());
        }
        if (isBody) {
            Long bodyId = article.getBodyId();
            articleVo.setBody(findArticleBodyById(bodyId));
        }
        if (isCategory) {
            Long categoryId = article.getCategoryId();
            articleVo.setCategory(categoryService.findCategoryById(categoryId));
        }
        return articleVo;
    }

    private ArticleBodyVo findArticleBodyById(Long articleId) {
        ArticleBody articleBody = articleBodyMapper.selectById(articleId);
        ArticleBodyVo articleBodyVo = new ArticleBodyVo();
        BeanUtils.copyProperties(articleBody, articleBodyVo);
        return articleBodyVo;
    }

}
